import { 
  AfterViewInit, 
  Component, 
  HostBinding, 
  Inject, 
  OnDestroy, 
  Optional, 
  ViewChild,
  ElementRef
} from '@angular/core';
import { 
  MAT_SNACK_BAR_DATA, 
  MatSnackBarRef,
  MatSnackBarConfig
} from '@angular/material/snack-bar';
import { Subscription } from 'rxjs';
import { MatButton, MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { CommonModule } from '@angular/common';
import { AnimationEvent } from '@angular/animations';
import { SafePipe } from '../../pipe/safe.pipe';
import { ToastMessage, ToastPanelData } from '@shared/models/toast.models';
import { onParentScrollOrWindowResize } from '@shared/utils';
import { AnimationTriggerMetadata, trigger, state, transition, style, animate } from '@angular/animations';

/** Toast 动画配置 */
export const toastAnimations: {
  readonly showHideToast: AnimationTriggerMetadata;
} = {
  showHideToast: trigger('showHideAnimation', [
    state('in', style({ transform: 'scale(1)', opacity: 1 })),
    transition('void => opened', [
      style({ transform: 'scale(0)', opacity: 0 }),
      animate('{{ open }}ms')
    ]),
    transition(
      'opened => closing',
      animate('{{ close }}ms', style({ transform: 'scale(0)', opacity: 0 }))
    )
  ])
};

/**
 * Toast 动画状态类型
 * - default: 默认 SnackBar 模式
 * - opened: 自定义面板模式
 * - closing: 关闭中
 */
export type ToastAnimationState = 'default' | 'opened' | 'closing';

/** Toast 组件 - 支持 SnackBar 和自定义面板两种模式 */
@Component({
  selector: 'cne-toast',
  templateUrl: './toast.component.html',
  styleUrls: ['toast.component.scss'],
  animations: [toastAnimations.showHideToast],
  standalone: true,
  imports: [CommonModule, MatButtonModule, MatIconModule, SafePipe]
})
export class ToastComponent implements AfterViewInit, OnDestroy {
  
  @ViewChild('actionButton') actionButton!: MatButton; // 关闭按钮引用
  
  @HostBinding('class') // 动态绑定面板样式类
  get panelClass(): string[] {
    return this.data?.panelClass || [];
  }

  /** 父容器元素引用（用于绝对定位） */
  private parentEl?: HTMLElement;
  /** SnackBar 容器元素引用（用于设置定位样式） */
  private snackBarContainerEl?: HTMLElement;
  /** 父容器滚动和窗口 resize 监听订阅 */
  private parentScrollSubscription?: Subscription;

  public notification: ToastMessage;
  animationState: ToastAnimationState;
  animationParams = {
    open: 100,
    close: 100
  };

  constructor(
    @Inject(MAT_SNACK_BAR_DATA) private data: ToastPanelData,
    private elementRef: ElementRef,
    @Optional() private snackBarRef?: MatSnackBarRef<ToastComponent>
  ) {
    // 根据是否有 snackBarRef 判断运行模式：有 → SnackBar 模式，无 → 自定义面板模式
    this.animationState = !!this.snackBarRef ? 'default' : 'opened';
    this.notification = data.notification;
  }

  ngAfterViewInit(): void {
    // SnackBar 模式下设置绝对定位，监听父容器滚动和窗口 resize
    if (this.snackBarRef && this.data.parent) {
      this.parentEl = this.data.parent.nativeElement;
      const container = this.elementRef.nativeElement.closest('.mat-mdc-snack-bar-container') as HTMLElement;
      
      if (container) {
        this.snackBarContainerEl = container;
        this.snackBarContainerEl.style.position = 'absolute';
        this.updateContainerRect();
        
        if (this.snackBarRef.containerInstance?.snackBarConfig) {
          this.updatePosition(this.snackBarRef.containerInstance.snackBarConfig);
        }
        
        if (this.parentEl) {
          this.parentScrollSubscription = onParentScrollOrWindowResize(this.parentEl).subscribe(() => {
            this.updateContainerRect();
          });
        }
      }
    }
  }

  /** 更新位置布局 */
  private updatePosition(config: MatSnackBarConfig): void {
    if (!this.snackBarContainerEl) {
      return;
    }

    const isRtl = config.direction === 'rtl';
    const isLeft = (config.horizontalPosition === 'left' ||
      (config.horizontalPosition === 'start' && !isRtl) ||
      (config.horizontalPosition === 'end' && isRtl));
    const isRight = !isLeft && config.horizontalPosition !== 'center';
    
    if (isLeft) {
      this.snackBarContainerEl.style.justifyContent = 'flex-start';
    } else if (isRight) {
      this.snackBarContainerEl.style.justifyContent = 'flex-end';
    } else {
      this.snackBarContainerEl.style.justifyContent = 'center';
    }
    
    if (config.verticalPosition === 'top') {
      this.snackBarContainerEl.style.alignItems = 'flex-start';
    } else {
      this.snackBarContainerEl.style.alignItems = 'flex-end';
    }
  }

  /** 更新容器位置 */
  private updateContainerRect(): void {
    if (!this.parentEl || !this.snackBarContainerEl) {
      return;
    }

    const viewportOffset = this.parentEl.getBoundingClientRect();
    this.snackBarContainerEl.style.top = viewportOffset.top + 'px';
    this.snackBarContainerEl.style.left = viewportOffset.left + 'px';
    this.snackBarContainerEl.style.width = viewportOffset.width + 'px';
    this.snackBarContainerEl.style.height = viewportOffset.height + 'px';
  }

  ngOnDestroy(): void {
    if (this.parentScrollSubscription) {
      this.parentScrollSubscription.unsubscribe();
    }
  }

  /** 关闭 Toast */
  action(event: MouseEvent): void {
    event.stopPropagation();
    event.preventDefault();
    
    if (this.snackBarRef) {
      this.snackBarRef.dismissWithAction();
    } else {
      this.animationState = 'closing';
    }
  }

  /** 动画结束回调 */
  onHideFinished(event: AnimationEvent): void {
    const { toState } = event;
    const isFadeOut = (toState as ToastAnimationState) === 'closing';
    const itFinished = this.animationState === 'closing';
    
    if (isFadeOut && itFinished) {
      this.data?.destroyToastComponent();
    }
  }
}
